Skip to content

Conversation

hageboeck
Copy link
Member

THLimitsFinder sometimes removes the first/last bin of an axis range. Here, it is ensured that the min and max of a buffered range is part of the axis range, and not removed by accident.
This fixes issues with TTree::Draw such as the one described in https://root-forum.cern.ch/t/bug-or-feature-in-ttree-draw/62862/

This supersedes #17689

@hageboeck hageboeck self-assigned this Aug 11, 2025
@hageboeck hageboeck added the skip ci Skip the full builds on the actions runners label Aug 11, 2025
Copy link

github-actions bot commented Aug 11, 2025

Test Results

    21 files      21 suites   3d 13h 22m 49s ⏱️
 3 661 tests  3 661 ✅ 0 💤 0 ❌
75 108 runs  75 108 ✅ 0 💤 0 ❌

Results for commit 7c7ad25.

♻️ This comment has been updated with latest results.

Copy link
Collaborator

@ferdymercury ferdymercury left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks!

I would propose this test:

TTree t;
Float_t x;
t.Branch("x", &x);
x = -999;
t.Fill();
x = 0;
t.Fill();
t.Draw("x");
auto h = (TH1*)gROOT->FindObject("htemp");
ASSERT_EQ(h->GetEntries(), h->GetEffectiveEntries());

@hageboeck hageboeck removed the skip ci Skip the full builds on the actions runners label Aug 13, 2025
@hageboeck hageboeck marked this pull request as ready for review August 13, 2025 15:06
@hageboeck
Copy link
Member Author

LGTM thanks!

I would propose this test:

TTree t;
Float_t x;
t.Branch("x", &x);
x = -999;
t.Fill();
x = 0;
t.Fill();
t.Draw("x");
auto h = (TH1*)gROOT->FindObject("htemp");
ASSERT_EQ(h->GetEntries(), h->GetEffectiveEntries());

@ferdymercury good test! It's added now.

Copy link
Collaborator

@ferdymercury ferdymercury left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Just a nitpick at the end of DrawAutoBinning:

delete h;
delete gROOT->FindObject("c1");

@hageboeck
Copy link
Member Author

Thanks! Just a nitpick at the end of DrawAutoBinning:

delete h;
delete gROOT->FindObject("c1");

👍, updated for h. The canvas isn't created in batch mode, though, so that should be be unnecessary in this test.

@ferdymercury
Copy link
Collaborator

The canvas isn't created in batch mode, though, so that should be be unnecessary in this test.

Are you sure?

root -l -b
root [0] TTree t;
root [1] Float_t x;
root [2] t.Branch("x", &x);
root [3] x = -999;
root [4] t.Fill();
root [5] x = 0;
root [6] t.Fill();
root [7] t.Draw("x");
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
root [8] gROOT->FindObject("c1")
(TObject *) 0x5c740608b9c0
root [9] delete gROOT->FindObject("c1")
root [10] gROOT->FindObject("c1")
(TObject *) nullptr

@hageboeck
Copy link
Member Author

The test failures for the graphics are real. This will require more investigation.

@hageboeck hageboeck force-pushed the limits_finder branch 3 times, most recently from 6397529 to 1a81a93 Compare August 18, 2025 13:56
@hageboeck hageboeck requested a review from dpiparo as a code owner August 18, 2025 13:56
@hageboeck hageboeck added the clean build Ask CI to do non-incremental build on PR label Aug 19, 2025
hageboeck and others added 2 commits September 15, 2025 16:01
During the merge of histograms with automatic axis ranges, the axis
range was computed when the fill buffer of the first histogram is full.
In this case, this was about halfway during the merge.
The resulting histogram was compared to one whose axis range was
computed on the full statistics, leading to slightly different axes.
By chance, the differences were within the tolerance, but in the commit
to follow, the axis range will be extended slightly to make the maximum
of a distribution part of the valid range. This will make the test fail.

This commit stabilises the test by extending the fill buffer of the first
histogram like for all the others in the test. In this way, all axis ranges
are computed on the same data.
- When asking THLimitsFinder to optimise axis limits, ask for a
  maximum slightly right of the actual maximum of the distribution.
  Otherwise, since the maximum may coincide with the maximum of the
  axis range, values may fall into the overflow.
- Use std::min / std::max to ensure that OptimizeLimits doesn't truncate
  any values.
- For symmetry reasons, also extend the range slightly to lower values.

This fixes the problem observed in
https://root-forum.cern.ch/t/bug-or-feature-in-ttree-draw/62862

Co-authored-by: ferdymercury <[email protected]>
Copy link
Contributor

@guitargeek guitargeek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much!

THLimitFinder tries to trim empty bins close to the end of an axis range,
but sometimes, the min/max was trimmed as well, so not all data would be
visible in the histogram.

Here, the case from the following post is tested:
https://root-forum.cern.ch/t/bug-or-feature-in-ttree-draw/

Co-authored-by: ferdymercury <[email protected]>
Co-authored-by: Jonas Rembser <[email protected]>
@hageboeck hageboeck merged commit 89511a2 into root-project:master Sep 23, 2025
68 of 72 checks passed
@hageboeck hageboeck deleted the limits_finder branch September 23, 2025 11:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clean build Ask CI to do non-incremental build on PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants